
import java.awt.*;
import java.io.*;
import java.util.*;

import javax.swing.*;

/**
 * The Assembler class - Converting "asm" to "bin" (Intermediate Format).
 * @author Hemant and Sandeep
 *
 */

public class Assem {
         public static String fillString(char filler, int count){
                char[] Cary = new char[count];
                while(count>0){ count--;  Cary[count] = filler ;   }
                return new String(Cary);
                }
         @SuppressWarnings("unchecked")
        public static void main(String args[]) throws IOException{
                 
                Vector<Vector<String>> vector1 = new Vector<Vector<String>>();
                Vector<String> vector2 = new Vector<String>();
                Vector<String> vector3 ;
                int m=0;
                int excep=0;
                String[] label = new String [50] ;
                BufferedWriter out = new BufferedWriter(new FileWriter("C:\\Users\\Hemanth\\Desktop\\assemblerout.txt"));
                //String[] Str1 = new String [10];
                Scanner s = null;
                String[] jumpaddr = new String[50];
                // Forming the Key Value pairs by using a Hasp-map, we can also use a Hash-table here!!      
        Hashtable<String, String> ht = new Hashtable<String,String>();
       
    // forming the Key value pairs for the Instructions both R-type and I-type
   
    ht.put("add","0000");
    ht.put("sub","0001");
    ht.put("and","0010");
    ht.put("or","0011");
    ht.put("nor","0100");
    ht.put("mult","0101");
    ht.put("sll","0110");
    ht.put("srl","0111");
    ht.put("sra","1000");
    ht.put("li","1001");
    ht.put("addi","1010");
    ht.put("load","1011");
    ht.put("store","1100");
    ht.put("bez","1101");
    ht.put("blz","1110");
    ht.put("jalr","1111");
    
    // forming the key value pairs for the registers
   
    ht.put("r0", "0000");
    ht.put("r1", "0001");
    ht.put("r2", "0010");
    ht.put("r3", "0011");
    ht.put("r4", "0100");
    ht.put("r5", "0101");
    ht.put("r6", "0110");
    ht.put("r7", "0111");
    ht.put("r8", "1000");
    ht.put("r9", "1001");
    ht.put("r10", "1010");
    ht.put("r11", "1011");
    ht.put("r12", "1100");
    ht.put("r13", "1101");
    ht.put("r14", "1110");
    ht.put("r15", "1111");
 /* ht.put("r16", "10000");
    ht.put("r17", "10001");
    ht.put("r18", "10010");
    ht.put("r19", "10011");
    ht.put("r20", "10100");
    ht.put("r21", "10101");
    ht.put("r22", "10110");
    ht.put("r23", "10111");
    ht.put("r24", "11000");
    ht.put("r25", "11001");
    ht.put("r26", "11010");
    ht.put("r27", "11011");
    ht.put("r28", "11100");
    ht.put("r29", "11101");
    ht.put("r30", "11110");
    ht.put("r31", "11111"); */
                File file = new File("C:\\Users\\Hemanth\\Desktop\\example.txt");
                Scanner scanner = null;
                try {
                        scanner = new Scanner(file);
                } catch(FileNotFoundException e) {
                        System.out.println("file not found: " + e.getMessage());
                }
                while(scanner.hasNextLine()) {
                        String line = scanner.nextLine();
                        vector2.addElement(line);
   
                }
                scanner.close();

                System.out.println("Vector2 Size " + vector2.size());

                for(int j = 0; j < vector2.size(); j++)
                {
                         
                        vector3 = new Vector() ;
                        s = new Scanner(vector2.get(j));
                        s.useDelimiter("\\s*,*\\s");
                                                while(s.hasNext())
                        {
                                vector3.addElement(s.next());
                               
                        }
                       
                        vector1.addElement(vector3);
                }
               

                
 /* m stores the no of branch statements and array label stores the all the
  *   labels found in the input in the following code.             
  */

                String bez = "bez" ;
                String blz = "blz" ;
                
                for (int n=0; n<vector1.size(); n++)
                System.out.println("no of lines " + vector1.size());
                
                
                for (int n=0; n<vector1.size(); n++)
               { int k=0;
               
                 if(((vector1.get(n)).get(0)).equals(bez)||((vector1.get(n)).get(0)).equals(blz))
                  {
                 
                    m++;
                   k=(vector1.get(n)).size();
                   label[m] = (vector1.get(n)).get(k-1);
                                   }
                 
                 
                }

 /* suppose this is the input
  *  bez r1, done
  * add  r1,r2,r3
  * done: add r4,r5,r4                                  
  * the following code stores the relative position of "done:" with respect to bez  
  * and stores it in count.  in this example, count = 2
  * O/P = bez r1, done
  *       add  r1,r2,r3
  *       add r4,r5,r4   (the " done:") is removed .
  */
                
                
                
        int x1[] = new int[50]; // x1 stores the position of bez, blz statment
        int x2[] = new int[50]; // x2 stores the position of label :
                
       for (int k=1; k<=m; k++)    
        {
                	 String lab = label[k] + ":" ;
                	 
           for (int n=0; n<vector1.size(); n++)
               
              {    int j=(vector1.get(n)).size();
                
               
             if(j>0)
             {      
               if((vector1.get(n)).get(j-1).equals(label[k]))
             
                 {  
                        x1[k] = n;
                 }
               
                          
                 if((vector1.get(n)).get(0).equals(lab))
                      {  
                              x2[k] = n;     	  
                    	  
                	  }      
            	    
                   }
                              
                           
                   
                 }
             }               
              
               // j++;
               
          
/* the following code checks for bez statement, and converts the label into the binary
* equivalent of the relative position of the target.
* eg: I/P  bez r1, done     O/P : bez r1, binary(2)
*           add  r1,r2,r3             add  r1,r2,r3    
*            add r4,r5,r4              add r4,r5,r4  (this was the target address)
*/
    
         for (int k=1; k<=m; k++)    
         {
                 	 String lab = label[k] + ":" ;
                 	 
            for (int n=0; n<vector1.size(); n++)
                
               {    int j=(vector1.get(n)).size();
         
               if(j>0)
               {
            	   if((vector1.get(n)).get(j-1).equals(label[k])) 
            		   
            	   {  	    
                int count = x1[k]-x2[k] ;
               String temp = (Integer.toBinaryString(count-1)) ;
                jumpaddr[k] = fillString('0',8-temp.length()) + temp; // forming the immediate value(16 bits)
                (vector1.get(n)).remove(j-1);
                (vector1.get(n)).add(jumpaddr[k]);
            	   }
         
               }
               
               
           }
         
         
         
         }  
         
         
         
         
               
      /*     
        int p=0; 
           for (int n=0; n<vector1.size(); n++)
           { int j=(vector1.get(n)).size();
             
           
              if(j>0) 
              {  
            	  if((vector1.get(n)).get(0).equals(bez)||(vector1.get(n)).get(0).equals(blz))
                  {   
                         p++;                 
                 
                     (vector1.get(n)).remove(j-1);
                    (vector1.get(n)).add(jumpaddr[p]);
                    ht.put((vector1.get(n)).get(j-1),(vector1.get(n)).get(j-1));
                   }
              }               
              
               
            }*/
        
               
                
                
                
             for(int n=0; n<vector1.size(); n++)
              {  int j=(vector1.get(n)).size() ;
                   String load = "load" ;
                   String store = "store" ;
                   
                if(j>0)
                 {		   
                   if((vector1.get(n)).get(0).equals(load)||(vector1.get(n)).get(0).equals(store))            
                     {   
                	          
                             
                      for(int r=0; r<(vector1.get(n)).get(j-1).length();r++ )
                      {  
                        if((vector1.get(n)).get(j-1).charAt(r)=='(')
                         {  String no = (vector1.get(n)).get(j-1).substring(0,r);
                            System.out.println("the value of no"+ no);
                            String reg = (vector1.get(n)).get(j-1).substring(r+1,((vector1.get(n)).get(j-1).length())-1) ;
                            (vector1.get(n)).remove(j-1);
                            (vector1.get(n)).add(reg);
                            System.out.println("the length of the string" + (vector1.get(n)).toString().length());
                            System.out.println("vector 1 line = " +(vector1.get(n)).toString() );
                            System.out.println("the value of reg "  +reg);
                              int temp = Integer.parseInt(no);
                              String offset = Integer.toBinaryString(temp);
                              offset = fillString('0',4-offset.length()) + offset ;
                              (vector1.get(n)).add(offset);
                              ht.put((vector1.get(n)).get(j),(vector1.get(n)).get(j));
                          }
                       }  
                     }
                  }  
              }
                  
             
             
             
            for(int n=0; n<vector1.size(); n++)
            {   int q = (vector1.get(n)).size();
                   String addi = "addi" ; String sll = "sll" ; String li = "li" ; 
                   String srl = "srl" ; String sra = "sra" ;
            if(q>1)
               {
            	//checking if the 1st word of the line is one of the above instructions.
            	 if((vector1.get(n)).get(0).equals(addi) || (vector1.get(n)).get(0).equals(sll)
           ||(vector1.get(n)).get(0).equals(li)||(vector1.get(n)).get(0).equals(srl)||(vector1.get(n)).get(0).equals(sra))	  
            	  
                   {  
                   String noimm = (vector1.get(n)).get(q-1) ;
                    int temp = Integer.parseInt(noimm);
                    int compaddi= (vector1.get(n)).get(0).compareTo(addi) ;
                    int compli  = (vector1.get(n)).get(0).compareTo(li);
                    String immvalue= null;   
                    if((compaddi*compli)!=0)// checking if the Ins is a shift Ins.
                       {
                    	   temp--; // if its a shift Ins, then shtamount-1 is stored in binary
                           if(temp<0) 
                              {System.out.println("wrong input to shift Ins");
                               excep =2;
                              }
                            immvalue = Integer.toBinaryString(temp);
                            int len= immvalue.length();
                           
                            if(len>4) 
                             immvalue=immvalue.substring(len-4,len);
                           else immvalue = fillString('0',4-immvalue.length()) + immvalue ; 
                           
                            
                       }   
                       
                    if(compaddi==0) //Checking if the Ins is addi   
                    {
                    	if(temp>8 || temp<-7)
                    	{ excep=3; // Input to addi should be -7 to +8 
                    	  System.out.println("wrong input to addi Ins");	
                    	}
                    
                    	 immvalue = Integer.toBinaryString(temp);
                        int len= immvalue.length();
                        
                         if(len>4) 
                          immvalue=immvalue.substring(len-4,len);
                        else immvalue = fillString('0',4-immvalue.length()) + immvalue ;
                    	
                    	
                    }
                    
                    
                    if(compli==0)
                    
                    { // if the input is beyond the range -127 to 128. then the LSB 8 bits 
                      // are taken as the input.	
                    	
                    	
                    
                    	 immvalue = Integer.toBinaryString(temp);
                        int len= immvalue.length();
                        
                         if(len>8) 
                          immvalue=immvalue.substring(len-8,len);
                        else immvalue = fillString('0',8-immvalue.length()) + immvalue ;
                    	
                    	
                    	}                                                                               
                    
                    (vector1.get(n)).remove(q-1);
                    (vector1.get(n)).add(immvalue);
                    ht.put((vector1.get(n)).get(q-1),(vector1.get(n)).get(q-1));
                    }
                }               
            	  
            	  
             }
                 
                  
                 
 /* converting the code into corresponding binary value and writting into output file 
  *  assemblerout.txt in the std MIPS format                 
  */
            int lineno=0; 
            
             for(int n=0; n<vector1.size(); n++)
                 { 
                	   int j=(vector1.get(n)).size();
                	   String line = "";
                       String k ="";
    
                       
             if(j>1)  // checking if the line contains only label           
             { 	   
                
     	       for(int i=0; i<j;i++)    
     	          	  
     	       
                line= line + ht.get((vector1.get(n)).get(i));
                 
             }
                  
     	      else      
                {      
                           line = fillString('0',16);
                }   
             
             if(line.length()<16)
            	 
             line = line + fillString('0',16-line.length());         	
              // checking for only label  	
             
             
             int h= line.compareTo(fillString('0',16));
             
                 if(h!=0)
                  {  lineno++;
                  
                	 line = lineno + " " + line + "  " + vector2.get(n) ;
                	 
                	 if(excep==0)
                     {out.write(line);
                      out.newLine();
                     }
                	 else
                	 { String error= "error" ;
                	   out.write(error);
                      out.newLine();
                     }	 
                     
                     
                  }
                  
                 
              }
                  out.close();
               


        }

       
}
